const { getObjectFromCache } = require('../service/requestAdmin');
const { engine } = require('../util/liquid');
/**
 * 设置 storeConfig、lang 和其他全局数据到 engine.options.globals 的中间件
 * 只从缓存获取数据，如果缓存中没有数据则抛出异常
 * 遵循项目缓存规范：深拷贝、TTL设置、错误处理
 * 注意：仅在页面访问时运行，API路由不使用此中间件
 *
 * 数据获取优先级：
 * 1. 缓存数据（唯一数据源）
 * 2. 缓存未命中时抛出异常
 */

/**
 * 缓存数据配置项
 * 添加新的缓存数据只需在这里添加配置即可
 */
const CACHE_CONFIGS = [
  {
    name: 'storeConfig',
    cacheKey: 'global_store_config',
    globalKey: 'storeConfig',
    displayName: 'storeConfig',
  },
  {
    name: 'langConfig',
    cacheKey: 'global_lang_config',
    globalKey: 'lang',
    displayName: 'lang',
  },
  {
    name: 'baseCurrency',
    cacheKey: 'global_base_currency',
    globalKey: 'base_currency',
    displayName: 'baseCurrency',
  },
  {
    name: 'cartNumber',
    cacheKey: 'global_cart_number',
    globalKey: 'cart_number',
    displayName: 'cartNumber',
  },
  {
    name: 'websiteDomain',
    cacheKey: 'global_website_domain',
    globalKey: 'website_domain',
    displayName: 'websiteDomain',
  },
  {
    name: 'currentDomain',
    cacheKey: 'global_current_domain',
    globalKey: 'current_domain',
    displayName: 'currentDomain',
  },
  {
    name: 'cSettings',
    cacheKey: 'global_c_settings',
    globalKey: 'variable_encrypt',
    displayName: 'cSettings',
  },
  {
    name: 'currencies',
    cacheKey: 'global_currencies',
    globalKey: 'currencies',
    displayName: 'currencies',
  },
  {
    name: 'currency',
    cacheKey: 'global_currency',
    globalKey: 'currency',
    displayName: 'currency',
  },
];

/**
 * 通用缓存数据获取函数
 * @param {Object} config - 缓存配置项
 * @param {Object} res - Express 响应对象
 * @returns {Object} { data, fromCache }
 */
function getCacheData(config, res) {
  const cacheResult = getObjectFromCache(config.cacheKey);

  if (cacheResult.success && cacheResult.data) {
    console.log(`[页面中间件] 从缓存获取 ${config.displayName} 成功`);
    return {
      data: cacheResult.data,
      fromCache: true,
    };
  } else {
    const errorMessage = `${config.displayName} 缓存数据不存在或已过期，缓存键: ${config.cacheKey}`;
    console.error(`[缓存异常] ${errorMessage}`);

    const errorData = {
      error: true,
      message: errorMessage,
      code: 404,
      timestamp: Date.now(),
      source: 'cache_miss',
      cacheKey: config.cacheKey,
    };

    // 设置响应头标识缓存异常
    const headerName = config.displayName.charAt(0).toUpperCase() + config.displayName.slice(1);
    res.set(`X-${headerName}-Error`, 'Cache miss');
    res.set('X-Cache-Status', 'MISS');

    return {
      data: errorData,
      fromCache: false,
    };
  }
}

/**
 * 设置全局数据到 engine.options.globals
 * @param {string} key - 全局数据键
 * @param {any} data - 数据
 * @param {boolean} fromCache - 是否来自缓存
 * @param {string} cacheKey - 缓存键
 */
function setGlobalData(key, data, fromCache, cacheKey) {
  // 进行深拷贝以避免引用问题（符合项目规范）
  engine.options.globals[key] = JSON.parse(JSON.stringify(data));

  // 添加元信息
  engine.options.globals[key]._meta = {
    fromCache: fromCache,
    timestamp: Date.now(),
    cacheKey: cacheKey,
  };
}

/**
 * 检查缓存异常并设置响应头
 * @param {Object} cacheResults - 缓存结果对象
 * @param {Object} res - Express 响应对象
 */
function handleCacheErrors(cacheResults, res) {
  const hasErrors = Object.values(cacheResults).some(result => result.data && result.data.error);

  if (hasErrors) {
    // 设置响应头警告
    Object.entries(cacheResults).forEach(([name, result]) => {
      if (result.data && result.data.error) {
        const config = CACHE_CONFIGS.find(c => c.name === name);
        if (config) {
          const headerName = config.displayName.charAt(0).toUpperCase() + config.displayName.slice(1);
          res.set(`X-${headerName}-Warning`, `${config.displayName} cache miss`);
          res.set(`X-${headerName}-Error-Code`, result.data.code || 404);
        }
      }
    });

    // 记录缓存异常日志
    const errorStatus = Object.entries(cacheResults)
      .map(([name, result]) => `${name}:${!!(result.data && result.data.error)}`)
      .join(', ');

    console.error(`[缓存异常] 数据获取失败 - ${errorStatus}`);
    console.warn('[中间件警告] 请求将继续处理，但使用的是异常状态数据');
  } else {
    // 记录成功日志
    const successStatus = Object.entries(cacheResults)
      .map(([name, result]) => {
        const config = CACHE_CONFIGS.find(c => c.name === name);
        const displayName = config ? config.displayName : name;
        return `${displayName}:${result.fromCache ? '(来自缓存)' : '(异常)'}`;
      })
      .join(', ');

    console.log(`[页面中间件] 所有配置设置成功 - ${successStatus}`);
  }
}

/**
 * 设置异常状态到 globals
 * @param {Error} error - 错误对象
 * @param {Object} res - Express 响应对象
 */
function setErrorStates(error, res) {
  if (!engine.options.globals) {
    engine.options.globals = {};
  }

  const errorState = {
    error: true,
    message: `中间件执行失败: ${error.message}`,
    code: 500,
    timestamp: Date.now(),
    source: 'middleware_exception',
    note: '中间件异常，无法获取缓存数据',
  };

  // 为所有配置设置异常状态
  CACHE_CONFIGS.forEach(config => {
    engine.options.globals[config.globalKey] = JSON.parse(JSON.stringify(errorState));
  });

  // 设置错误响应头
  CACHE_CONFIGS.forEach(config => {
    const headerName = config.displayName.charAt(0).toUpperCase() + config.displayName.slice(1);
    res.set(`X-${headerName}-Error`, 'Middleware execution failed');
  });

  res.set('X-Cache-Status', 'ERROR');
  res.set('X-Data-Source', 'none');
}
module.exports = async function setStoreConfigMiddleware(req, res, next) {
  try {
    // 初始化 engine.options.globals
    if (!engine.options.globals) {
      engine.options.globals = {};
    }

    // 获取所有缓存数据
    const cacheResults = {};
    CACHE_CONFIGS.forEach(config => {
      cacheResults[config.name] = getCacheData(config, res);
    });

    // 设置全局数据
    CACHE_CONFIGS.forEach(config => {
      const result = cacheResults[config.name];
      setGlobalData(config.globalKey, result.data, result.fromCache, config.cacheKey);
    });

    // 检查缓存异常并设置响应头
    handleCacheErrors(cacheResults, res);

    next();
  } catch (error) {
    console.error('[中间件] setStoreConfigMiddleware 执行失败:', error);
    setErrorStates(error, res);
    console.error('[严重错误] 中间件异常，无缓存数据可用，请求将继续但数据异常');
    next();
  }
};
